/************************************************************************
 *
 * stdlib.h
 *
 * (c) Copyright 1996-2004 Analog Devices, Inc.  All rights reserved.
 * $Revision: 6 $
 ************************************************************************/

#pragma once
#ifndef __NO_BUILTIN
#pragma system_header /* stdlib.h */
#endif

#ifndef __STDLIB_DEFINED
#define __STDLIB_DEFINED

#ifndef _YVALS
  #include <yvals.h>
#endif

#ifndef NULL
   #ifdef __cplusplus
      #define NULL  0
   #else
      #define NULL  ((void *)0)
   #endif
#endif

#define EXIT_FAILURE 1
#define EXIT_SUCCESS 0
#define RAND_MAX 2147483647
#define MB_CUR_MAX 1

#ifndef __SIZE_T_DEFINED
   #define __SIZE_T_DEFINED
   typedef long unsigned int size_t;
#endif

#if !defined(__WCHAR_T_DEFINED) && !defined(_WCHART)
   #define __WCHAR_T_DEFINED
   #define _WCHART
   typedef _Wchart wchar_t;
#endif

typedef struct {
  int quot;
  int rem;
} div_t;

typedef struct {
  long int quot;
  long int rem;
} ldiv_t;


#ifdef __TS_BYTE_ADDRESS
#include <byteaddrdef.h>
#endif


/*==============================================================*/
/* Prototypes for library routines
 */
#ifdef __cplusplus
extern "C" {
#endif

#ifdef __TS_BYTE_ADDRESS
float       _atoff_ba(const char*);
float       _strtof_ba(const char*, char**);
typedef int _Cmpfun(const void*, const void*);
#else
float       _atoff(const char*);
float       _strtof(const char*, char**);
#endif
long double _atold(const char*); 
long double _strtold(const char*, char**);
int  atoi(const char*);
long atol(const char*);
long long atoll(const char*);
long          strtol(const char*, char**, int);
long long     strtoll(const char*, char**, int);
int          _strtoi(const char*, char**, int);
unsigned long strtoul(const char*, char**, int);
unsigned long long strtoull(const char*, char**, int);

int  rand(void);
void srand(unsigned int);

void *calloc(size_t, size_t);
void  free(void*);
void *malloc(size_t);
void *realloc (void*, size_t);

/* Analog extensions for heap management */
int   _heap_init(int);
#ifndef _ADI_THREADS
  /* This feature is not available in multi threaded environments
     Use malloc, calloc, realloc and free to access the system (=default) heap, 
     heap_malloc, heap_calloc, heap_realloc and heap_free on all other heaps
  */
  int   _heap_switch(int); 
#endif
int   _heap_lookup(int);
void *_heap_calloc(int, size_t, size_t);
void  _heap_free(int, void*);
void *_heap_malloc(int, size_t);
void *_heap_realloc(int, void*, size_t);
int   _heap_install(void *base, size_t length, int heapid);

/* This struct is needed for programs that declare non-default
 * heaps in C source files.
 */
typedef struct {
  char  *_start;   /* start address of heap */
  size_t _size;    /* size of heap in chars (not words) */
  int    _user_id; /* user id of heap */
} _heap_descriptor_t;

#define MAXHEAPS  4 /* The maximum number of multiple heaps that can be
                     * initialised at run-time.
                     */

void  abort(void);
void  exit(int);
char *getenv(const char*);
int   system(const char*);


typedef void _t_atexit_fp(void);
typedef int _t_compare_fp(const void *, const void *);

int   atexit(_t_atexit_fp);

void *bsearch(const void*, const void*, size_t, size_t, _t_compare_fp);
void  qsort(void*, size_t, size_t, _t_compare_fp);

#ifdef __cplusplus
} /* extern "C" */

/* C++ linkage */
typedef int _t_cpp_compare_fp(const void *, const void *);

#pragma always_inline
__inline int atexit(void (*_func)(void))
{
  return atexit( (_t_atexit_fp *) _func);
}

#pragma always_inline
__inline void *bsearch(const void* _key, const void* _base, 
                       size_t _nelem, size_t _size, _t_cpp_compare_fp _func)
{
  return bsearch(_key, _base, _nelem, _size, (_t_compare_fp *) _func); 
}

#pragma always_inline
__inline void qsort(void* _base, size_t _nelem, 
                    size_t _size, _t_cpp_compare_fp _func)
{
  return qsort(_base, _nelem, _size, (_t_compare_fp *) _func);
}

extern "C" {
#endif



/* Mathematical (integer) functions */
int    abs(int);
div_t  div(int, int);
long   labs(long);
ldiv_t ldiv(long, long);

#if defined(__cplusplus)
} /* extern "C" */

extern "C++" {
  #pragma always_inline
  __inline ldiv_t div(long _numer, long _denom)
  {
     return ldiv(_numer,_denom);
  }
}  /* extern "C++" */

extern "C" {
#endif

int _avg(int, int);    /* (a+b)/2 */
int _clip(int ,int);   /* bound a by b (positive and negative) */
int _max(int, int);    /* maximum */
int _min(int, int);    /* minimum */
int _count_ones(int);  /* number of "1" bits */

   /* "long int" versions */
long _lavg(long, long);
long _lclip(long, long);
long _lmax(long, long);
long _lmin(long, long);
int  _lcount_ones(long);

   /* "long long" versions */
long long _llabs(long long);
long long _llavg(long long, long long);
long long _llclip(long long, long long);
long long _llmax(long long, long long);
long long _llmin(long long, long long);
int       _llcount_ones(long long);

/* bit-reversed addition */
int _addbitrev(int, int);

int    mblen(const char*, size_t);
size_t mbstowcs(wchar_t*, const char*, size_t);
int    mbtowc(wchar_t*, const char*, size_t);
size_t wcstombs(char*, const wchar_t*, size_t);
int    wctomb(char*, wchar_t);

/*==============================================================*/
/* Available builtin functions. These may be called directly to
 * obtain compiler-generated inline assembly instructions.
 */
int __builtin_abs(int);     /* absolute value */
long __builtin_labs(long);
long long __builtin_llabs(long long);

int __builtin_avg(int, int);    /* (a+b)/2 */
int __builtin_clip(int, int);   /* bound a by b (positive and negative) */
int __builtin_max(int, int);    /* maximum */
int __builtin_min(int, int);    /* minimum */
int __builtin_count_ones(int);  /* number of "1" bits */

long __builtin_lavg(long, long);
long __builtin_lclip(long, long);
long __builtin_lmax(long, long);
long __builtin_lmin(long, long);
int __builtin_lcount_ones(long);

long long __builtin_llavg(long long, long long);
long long __builtin_llclip(long long, long long);
long long __builtin_llmax(long long, long long);
long long __builtin_llmin(long long, long long);
int __builtin_llcount_ones(long long);

int __builtin_addbitrev(int, int);

#ifdef __cplusplus
  }
#endif

/*==============================================================*/
/* Inline wrappers for some library functions and builtins
 */
#ifdef __cplusplus
  extern "C++" {
#endif
#ifdef __ANALOG_EXTENSIONS__
  #ifdef __DOUBLES_ARE_FLOATS__
    #ifndef __TS_BYTE_ADDRESS
    /* __inline double atof(const char *nptr) */
    /*     {return _atoff_ba(nptr);} */
    /* __inline double strtod(const char *nptr, char **endptr) */
    /*     {return _strtof_ba(nptr, endptr);} */
    /*#else */
    #pragma always_inline
    __inline double atof(const char *nptr)
        {return _atoff(nptr);}
    #pragma always_inline
    __inline double strtod(const char *nptr, char **endptr)
        {return _strtof(nptr, endptr);}
    #endif
  #else /* doubles are long doubles */
    #pragma always_inline
    __inline double atof(const char *nptr)
        {return _atold(nptr);}
    #pragma always_inline
    __inline double strtod(const char *nptr, char **endptr)
        {return _strtold(nptr, endptr);}
  #endif
  #ifdef __cplusplus
    extern "C" {
  #endif
  /* The following inline definitions provide function
   * implementations for routines that otherwise would be
   * available only as builtins. These are declared with "C"
   * linkage because they are effectively substitutes for
   * absent library implementations. If overloaded versions
   * are desired for C++ compilations, these would use the
   * function name without the leading underscore, e.g. an
   * overloaded "avg" that covers _avg, _lavg, and llavg.
   */
  #pragma always_inline
  __inline int addbitrev(int _i, int _j)
      {return __builtin_addbitrev(_i, _j);}
  #pragma always_inline
  __inline int avg(int _i, int _j)
      {return __builtin_avg(_i, _j);}
  #pragma always_inline
  __inline int count_ones(int _i)
      {return __builtin_count_ones(_i);}
  #pragma always_inline
  __inline long _labs(long _j)
      {return __builtin_labs(_j);}
  #pragma always_inline
  __inline long lavg(long _a, long _b)
      {return __builtin_lavg(_a, _b);}
  #pragma always_inline
  __inline long lclip(long _a, long _b)
      {return __builtin_lclip(_a, _b);}
  #pragma always_inline
  __inline int lcount_ones(long _numb)
      {return __builtin_lcount_ones(_numb);}
  #pragma always_inline
  __inline long long llabs(long long _j)
      {return __builtin_llabs(_j);}
  #pragma always_inline
  __inline long long llavg(long long _a, long long _b)
      {return __builtin_llavg(_a, _b);}
  #pragma always_inline
  __inline long long llclip(long long _a, long long _b)
      {return __builtin_llclip(_a, _b);}
  #pragma always_inline
  __inline int llcount_ones(long long _i)
      {return __builtin_llcount_ones(_i);}
  #pragma always_inline
  __inline long long llmax(long long _a, long long _b)
      {return __builtin_llmax(_a, _b);}
  #pragma always_inline
  __inline long long llmin(long long _a, long long _b)
      {return __builtin_llmin(_a, _b);}
  #pragma always_inline
  __inline long lmax(long _a, long _b)
      {return __builtin_lmax(_a, _b);}
  #pragma always_inline
  __inline long lmin(long _a, long _b)
      {return __builtin_lmin(_a, _b);}
  #ifdef __cplusplus
     }
  #endif
  #ifdef __cplusplus
    /* C++ overloads go here, if any */
  #endif
#endif
#ifdef __cplusplus
  }
#endif

/*==============================================================*/
/* These macros provide the C standard names for routines that
 * have two versions. The appropriate version depends on whether
 * doubles are 32 or 64 bits.
 */
#ifdef __DOUBLES_ARE_FLOATS__
#ifdef __TS_BYTE_ADDRESS
  #define atof   _atoff_ba
  #define strtod _strtof_ba
#else
  #define atof   _atoff
  #define strtod _strtof
#endif
#else /* doubles are 64-bits */
  #define atof _atold
  #define strtod _strtold
#endif /* __DOUBLES_ARE_FLOATS__ */

/*==============================================================*/
/* These macros will cause the compiler to substitute inline
 * assembly instructions for a function call.
 */
#ifndef __NO_BUILTIN
  #define abs(j)    __builtin_abs(j)
  #define labs(j)   __builtin_labs(j)
  #define _llabs(j) __builtin_llabs(j)

  #define _avg(i, j)   __builtin_avg(i, j)
  #define _clip(i, j)  __builtin_clip(i, j)
  #define _max(i, j)   __builtin_max(i, j)
  #define _min(i, j)   __builtin_min(i, j)
  #define _count_ones(j) __builtin_count_ones(j)

  #define _lavg(i, j)  __builtin_lavg(i, j)
  #define _lclip(i, j) __builtin_lclip(i, j)
  #define _lmax(i, j)  __builtin_lmax(i, j)
  #define _lmin(i, j)  __builtin_lmin(i, j)
  #define _lcount_ones(j) __builtin_lcount_ones(j)

  #define _llavg(i, j)  __builtin_llavg(i, j)
  #define _llclip(i, j) __builtin_llclip(i, j)
  #define _llmax(i, j)  __builtin_llmax(i, j)
  #define _llmin(i, j)  __builtin_llmin(i, j)
  #define _llcount_ones(j) __builtin_llcount_ones(j)

  #define _addbitrev(i, j) __builtin_addbitrev(i, j)
#endif /* __NO_BUILTIN */

/*==============================================================*/
/* These macros provide names not beginning with an underscore
 * for Analog extensions. If these macros conflict with program
 * symbols, they can be undefined. In that case, the library
 * routines can still be accessed via the name with the leading
 * underscore.
 */
#define avg  _avg
#define clip _clip

#if defined(__cplusplus)
extern "C" {
  #pragma always_inline
  __inline int  max(int _a, int _b)
  {
    return ( _a > _b ? _a : _b );
  }

  #pragma always_inline
  __inline int  min(int _a, int _b)
  {
    return ( _a < _b ? _a : _b );
  }
}
#else
#define max  _max
#define min  _min
#endif

#define count_ones _count_ones

#define lavg  _lavg
#define lclip _lclip
#define lmax  _lmax
#define lmin  _lmin
#define lcount_ones _lcount_ones

#define llabs  _llabs
#define llavg  _llavg
#define llclip _llclip
#define llmax  _llmax
#define llmin  _llmin
#define llcount_ones _llcount_ones

#define atold   _atold
#define strtold _strtold

#define addbitrev _addbitrev
#define strtoi _strtoi
#ifdef __TS_BYTE_ADDRESS
#define strtof _strtof_ba
#else
#define strtof _strtof
#endif

#define heap_init    _heap_init
#define heap_switch  _heap_switch
#define heap_lookup  _heap_lookup
#define heap_calloc  _heap_calloc
#define heap_free    _heap_free
#define heap_malloc  _heap_malloc
#define heap_realloc _heap_realloc
#define heap_install _heap_install

#endif /* __STDLIB_DEFINED */
